package ${package}.${moduleName}.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import lombok.AllArgsConstructor;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.ht.finance.vo.ImportResultAllocation;
import com.ht.framework.common.exception.ServerException;
import com.ht.framework.common.utils.DateUtils;
import com.ht.framework.common.utils.ExcelUtils;
import com.ht.framework.mybatis.service.impl.BaseServiceImpl;
import com.ht.framework.common.utils.PageResult;
import com.ht.finance.convert.${ClassName}Convert;
import com.ht.finance.entity.${ClassName}Entity;
import com.ht.finance.query.${ClassName}Query;
import com.ht.finance.vo.${ClassName}VO;
import com.ht.finance.dao.${ClassName}Dao;
import com.ht.finance.service.${ClassName}Service;
import com.ht.finance.vo.ImportResultAllocation;
import org.springframework.web.multipart.MultipartFile;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import cn.hutool.core.collection.CollectionUtil;
import com.ht.finance.query.${ClassName}ExcelQuery;

import java.util.List;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;

/**
 * ${tableComment}
 *
 * @author ${author} ${email}
 * @since ${version} ${date}
 */
@Service
@AllArgsConstructor
public class ${ClassName}ServiceImpl extends BaseServiceImpl<${ClassName}Dao, ${ClassName}Entity> implements ${ClassName}Service {

    @Override
    public PageResult<${ClassName}VO> page(${ClassName}Query query) {
        IPage<${ClassName}Entity> page = baseMapper.selectPage(getPage(query), getWrapper(query));

        return new PageResult<>(${ClassName}Convert.INSTANCE.convertList(page.getRecords()), page.getTotal());
    }
        @Override
        public PageResult<${ClassName}VO> pageWithSql(${ClassName}Query query) {
            IPage<${ClassName}VO> page = baseMapper.selectPageWithSql(getPage(query),query);
                return new PageResult<>(page.getRecords(), page.getTotal());
       }

    private LambdaQueryWrapper<${ClassName}Entity> getWrapper(${ClassName}Query query){
        LambdaQueryWrapper<${ClassName}Entity> wrapper = Wrappers.lambdaQuery();
        <#list queryList as field>
            <#if field.queryFormType == 'date' || field.queryFormType == 'datetime'>
        wrapper.between(ArrayUtils.isNotEmpty(query.get${field.attrName?cap_first}()), ${ClassName}Entity::get${field.attrName?cap_first}, ArrayUtils.isNotEmpty(query.get${field.attrName?cap_first}()) ? query.get${field.attrName?cap_first}()[0] : null, ArrayUtils.isNotEmpty(query.get${field.attrName?cap_first}()) ? query.get${field.attrName?cap_first}()[1] : null);
            <#elseif field.queryType == '='>
        wrapper.eq(StringUtils.isNotEmpty(query.get${field.attrName?cap_first}()), ${ClassName}Entity::get${field.attrName?cap_first}, query.get${field.attrName?cap_first}());
            <#elseif field.queryType == '!='>
        wrapper.ne(StringUtils.isNotEmpty(query.get${field.attrName?cap_first}()), ${ClassName}Entity::get${field.attrName?cap_first}, query.get${field.attrName?cap_first}());
            <#elseif field.queryType == '>'>
        wrapper.gt(StringUtils.isNotEmpty(query.get${field.attrName?cap_first}()), ${ClassName}Entity::get${field.attrName?cap_first}, query.get${field.attrName?cap_first}());
            <#elseif field.queryType == '>='>
        wrapper.ge(StringUtils.isNotEmpty(query.get${field.attrName?cap_first}()), ${ClassName}Entity::get${field.attrName?cap_first}, query.get${field.attrName?cap_first}());
            <#elseif field.queryType == '<'>
        wrapper.lt(StringUtils.isNotEmpty(query.get${field.attrName?cap_first}()), ${ClassName}Entity::get${field.attrName?cap_first}, query.get${field.attrName?cap_first}());
            <#elseif field.queryType == '<='>
        wrapper.le(StringUtils.isNotEmpty(query.get${field.attrName?cap_first}()), ${ClassName}Entity::get${field.attrName?cap_first}, query.get${field.attrName?cap_first}());
            <#elseif field.queryType == 'like'>
        wrapper.like(StringUtils.isNotEmpty(query.get${field.attrName?cap_first}()), ${ClassName}Entity::get${field.attrName?cap_first}, query.get${field.attrName?cap_first}());
            <#elseif field.queryType == 'left like'>
        wrapper.likeLeft(StringUtils.isNotEmpty(query.get${field.attrName?cap_first}()), ${ClassName}Entity::get${field.attrName?cap_first}, query.get${field.attrName?cap_first}());
            <#elseif field.queryType == 'right like'>
        wrapper.likeRight(StringUtils.isNotEmpty(query.get${field.attrName?cap_first}()), ${ClassName}Entity::get${field.attrName?cap_first}, query.get${field.attrName?cap_first}());
            </#if>
        </#list>
        return wrapper;
    }

                        private LambdaQueryWrapper<${ClassName}Entity> getWrapper(${ClassName}ExcelQuery query){
                            LambdaQueryWrapper<${ClassName}Entity> wrapper = Wrappers.lambdaQuery();
                                <#list queryList as field>
                                    <#if field.queryFormType == 'date' || field.queryFormType == 'datetime'>
                                        wrapper.between(ArrayUtils.isNotEmpty(query.get${field.attrName?cap_first}()), ${ClassName}Entity::get${field.attrName?cap_first}, ArrayUtils.isNotEmpty(query.get${field.attrName?cap_first}()) ? query.get${field.attrName?cap_first}()[0] : null, ArrayUtils.isNotEmpty(query.get${field.attrName?cap_first}()) ? query.get${field.attrName?cap_first}()[1] : null);
                                    <#elseif field.queryType == '='>
                                        wrapper.eq(StringUtils.isNotEmpty(query.get${field.attrName?cap_first}()), ${ClassName}Entity::get${field.attrName?cap_first}, query.get${field.attrName?cap_first}());
                                    <#elseif field.queryType == '!='>
                                        wrapper.ne(StringUtils.isNotEmpty(query.get${field.attrName?cap_first}()), ${ClassName}Entity::get${field.attrName?cap_first}, query.get${field.attrName?cap_first}());
                                    <#elseif field.queryType == '>'>
                                        wrapper.gt(StringUtils.isNotEmpty(query.get${field.attrName?cap_first}()), ${ClassName}Entity::get${field.attrName?cap_first}, query.get${field.attrName?cap_first}());
                                    <#elseif field.queryType == '>='>
                                        wrapper.ge(StringUtils.isNotEmpty(query.get${field.attrName?cap_first}()), ${ClassName}Entity::get${field.attrName?cap_first}, query.get${field.attrName?cap_first}());
                                    <#elseif field.queryType == '<'>
                                        wrapper.lt(StringUtils.isNotEmpty(query.get${field.attrName?cap_first}()), ${ClassName}Entity::get${field.attrName?cap_first}, query.get${field.attrName?cap_first}());
                                    <#elseif field.queryType == '<='>
                                        wrapper.le(StringUtils.isNotEmpty(query.get${field.attrName?cap_first}()), ${ClassName}Entity::get${field.attrName?cap_first}, query.get${field.attrName?cap_first}());
                                    <#elseif field.queryType == 'like'>
                                        wrapper.like(StringUtils.isNotEmpty(query.get${field.attrName?cap_first}()), ${ClassName}Entity::get${field.attrName?cap_first}, query.get${field.attrName?cap_first}());
                                    <#elseif field.queryType == 'left like'>
                                        wrapper.likeLeft(StringUtils.isNotEmpty(query.get${field.attrName?cap_first}()), ${ClassName}Entity::get${field.attrName?cap_first}, query.get${field.attrName?cap_first}());
                                    <#elseif field.queryType == 'right like'>
                                        wrapper.likeRight(StringUtils.isNotEmpty(query.get${field.attrName?cap_first}()), ${ClassName}Entity::get${field.attrName?cap_first}, query.get${field.attrName?cap_first}());
                                    </#if>
                                </#list>
                                return wrapper;
                                }

    @Override
    public void save(${ClassName}VO vo) {
        ${ClassName}Entity entity = ${ClassName}Convert.INSTANCE.convert(vo);

        baseMapper.insert(entity);
    }

    @Override
    public void update(${ClassName}VO vo) {
        ${ClassName}Entity entity = ${ClassName}Convert.INSTANCE.convert(vo);

        updateById(entity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(List<Long> idList) {
        removeByIds(idList);
    }

     @Override
     public ImportResultAllocation<${ClassName}VO> importExcelNew(MultipartFile file) {
     List<String> headers =  Arrays.asList();
     List<Integer> failedCountRow = new ArrayList<>();
     ExcelReader reader = null;
     ImportResultAllocation<${ClassName}VO> result = new ImportResultAllocation<${ClassName}VO>();
     try {
          reader = ExcelUtil.getReader(file.getInputStream());
          List<List<Object>> read = reader.read(0);
          List<Object> headerList = read.get(0); //表头
          headerList.forEach(e->{
          if (!headers.contains(e.toString())){
          throw new ServerException("表头不正确:"+e.toString()+"，您可以先下载模板");
          }
                  });
                     } catch (IOException e) {
             throw new RuntimeException("文件格式异常，仅支持 .xlsx 后缀");
               }

            ExcelListener excelListener = new ExcelListener();
             List<${ClassName}VO> dataList = null;
            try {
            EasyExcel.read(file.getInputStream(), ${ClassName}VO.class, excelListener).sheet().doRead();
             dataList = excelListener.getDataList();
              if (CollectionUtil.isNotEmpty(dataList)) {
                List<${ClassName}VO> failedRecords = new ArrayList<>();
                for (int i = 0; i < dataList.size(); i++) {

                  this.save(dataList.get(i));
                    }


                         int successCount = dataList.size() - failedRecords.size();
                          result.setSuccessCount(successCount);
                          result.setFailedCount(failedRecords.size());
                          result.setFailedRecords(failedRecords);
                           result.setFailedCountRow(failedCountRow);
                            } else {
                              result.setSuccessCount(0);
                                                        result.setFailedCount(0);
                                                        }
                                                        } catch (Exception e) {
                                                        e.printStackTrace();
                                                        result.setSuccessCount(0);
                                                        result.setFailedCount(dataList.size());
                                                        result.setFailedRecords(dataList); // 如果发生异常，将所有记录标记为失败
                                                        }

                                                        return result;
                                                        }

                                                        public static class ExcelListener extends AnalysisEventListener<${ClassName}VO> {

                                                            private List<${ClassName}VO> dataList = new ArrayList<>();
                                                                public List<${ClassName}VO> getDataList() {
                                                                    return dataList;
                                                                    }
                                                                    public void setDataList(List<${ClassName}VO> dataList) {
                                                                        this.dataList = dataList;
                                                                        }
                                                                        @Override
                                                                        public void invoke(${ClassName}VO vo, AnalysisContext analysisContext) {
                                                                        dataList.add(vo);

                                                                        }

                                                                        @Override
                                                                        public void doAfterAllAnalysed(AnalysisContext analysisContext) {

                                                                        }
                                                                        }


                                                                        @Override
                                                                        public void export(${ClassName}ExcelQuery query) {
                                                                        List<${ClassName}Entity> entities = baseMapper.selectListWithSql(query);
                                                                            List<${ClassName}VO> vos = ${ClassName}Convert.INSTANCE.convertList(entities);

                                                                                ExcelUtils.excelExport(${ClassName}VO.class,"${ClassName}" + DateUtils.format(new Date()), null, vos);
                                                                                }
}